﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace BCCommon
{
    /// <summary>
    /// AES工具
    /// </summary>
    public static class AESUtils
    {
        private static readonly string keyStr = "xablackcoffee312";
        private static readonly string ivStr = "blackcoffee18312";//偏移量,最小为16
        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="str">解密字符串</param>
        /// <returns></returns>
        public static string AESEncrypt(string str)
        {
            var encryptKey = Encoding.UTF8.GetBytes(keyStr);
            using (var aesAlg = Aes.Create())
            {
                aesAlg.Padding = PaddingMode.PKCS7;
                aesAlg.Mode = CipherMode.CBC;
                aesAlg.IV = Encoding.UTF8.GetBytes(ivStr);
                using (var encryptor = aesAlg.CreateEncryptor(encryptKey, aesAlg.IV))
                {
                    using (var msEncrypt = new MemoryStream())
                    {
                        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor,
                            CryptoStreamMode.Write))

                        using (var swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(str);
                        }
                        var decryptedContent = msEncrypt.ToArray();
                        return BytesToHex(decryptedContent);
                    }
                }
            }
        }
        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="str">解密字符串</param>
        /// <returns></returns>
        public static string AESDecrypt(string str)
        {
            string result = string.Empty;
            byte[] inputBytes = HexToBytes(str);
            
            using (var aesAlg = Aes.Create())
            {
                aesAlg.Key = Encoding.UTF8.GetBytes(keyStr);
                aesAlg.IV = Encoding.UTF8.GetBytes(ivStr);
                aesAlg.Padding = PaddingMode.PKCS7;
                aesAlg.Mode = CipherMode.CBC;
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                
                using (MemoryStream msEncrypt = new MemoryStream(inputBytes))
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srEncrypt = new StreamReader(csEncrypt))
                        {
                            Encoding encoding = srEncrypt.CurrentEncoding;
                            result = srEncrypt.ReadToEnd();

                        }
                    }
                }
            }
            return result;
        }

        private static byte[] HexToBytes(string s)
        {
            s = s.ToUpper();
            int length = s.Length / 2;
            byte[] buffer = new byte[length];

            char[] hexChars = s.ToCharArray();
            for (int i = 0; i < length; i++)
            {
                int pos = i * 2;
                buffer[i] = (byte)(charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
            }
            //for (int i = 0; i < s.Length; i += 2)
            //    buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }

        private static byte charToByte(char c)
        {
            return (byte)"0123456789ABCDEF".IndexOf(c);
        }

        private static string BytesToHex(byte[] data)
        {
            StringBuilder sb = new StringBuilder(data.Length * 3);
            foreach (byte b in data)
            {
                //16进制数字
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
                //16进制数字之间以空格隔开
                //sb.Append(Convert.ToString(b, 16).PadLeft(2, '0').PadRight(3, ' '));
            }
            return sb.ToString().ToUpper();
        }
    }
}
